This invention relates to object-oriented programming and particularly to an object""s method execution during run-time.
In class-based Object orientated Programs such as C++ and Java, a xe2x80x9cclassxe2x80x9d is a template that defines an object""s methods and variables. A class can have sub-classes that can inherit some or all of the characteristics of the class. Subclasses can defines new methods that are not themselves defined in the parent class. It is sometimes desirable to have different implementations of an object""s methods within a single system where the choice of implementation depends upon various dynamic run-time, attributes, e.g. different implementations for sparse and dense matrices. To some extent, this can be achieved by sub-classing; however, sub-classing cannot be used to change the behavior of an existing object. Further, sub-classing requires explicit programmer action to determine the type of object to create.
By way of specific example, consider distributed object-based systems that often use proxies to represent remote objects. When a client invokes a method on the proxy, the code found at the method""s entry in the virtual method table will redirect the invocation to the master object at the server. Proxies can perform various types of caching; however, all instances of a proxy for a particular class of remote object perform the same caching algorithm. In addition, proxies are not transparent to the programmer: a user can typically tell the difference between the run-time type of the proxy and the master object (if the language being used allows determination of an object""s run-time type). Further, if an object migrates, the source node cannot continue using its existing references to the object; changing the implementation of an object from master to proxy requires changing the identity of the object (as well as its run-time type) Finally, since all proxies for a given class typically execute the same code, there is no way for the system to customize the behavior of a particular instance of a proxy at run-time based upon changing resource characteristics of the executing platform.
Aspects of the problem have been addressed in the art, albeit not entirely satisfactorily. For example, the xe2x80x9cSmalltalkxe2x80x9d language includes the ability to exchange one object with another using the symmetric definition of the xe2x80x9cbecome:xe2x80x9d message, such that:
a become: b
causes all pointers to object xe2x80x9caxe2x80x9d to point to object xe2x80x9cbxe2x80x9d, and vice versa. This is the original definition of xe2x80x9cbecome:xe2x80x9d. The asymmetric or one-way definition was added later in order to preserve compatibility between older versions of Smalltalk, where object pointers were indices placed into an indirection table. The implementation of xe2x80x9cbecome:xe2x80x9d merely required swapping pointers in the table. For later implementations not based on the indirection table, the implementation of xe2x80x9cbecome:xe2x80x9d required scanning all the memory for pointers to the first object. Therefore, these later implementations generally opted for the asymmetric semantics, wherein the definition of xe2x80x9cbxe2x80x9d is unchanged. Thus, all pointers to object xe2x80x9caxe2x80x9d will now point to object xe2x80x9cbxe2x80x9d and all (old) pointers to object xe2x80x9cbxe2x80x9d remain unchanged.
In any case, it is not clear how to ensure consistency between the two definitions in a multithreaded environment. Further, use of a specific implementation of xe2x80x9cbecomexe2x80x9d in an application is not orthogonal to the application but, rather, requires explicit programmer intervention. Also, it does not change the implementation for an existing object, but rather changes the object referred to by a particular reference. Whilst this can be used to obtain some of the effect of changing the implementation of an existing object, it requires the program explicitly to construct the new object which is to be the replacement. Finally, objects with different implementations have different run-time types.
In chapter 10 of xe2x80x9cAdvanced C++xe2x80x9d by James O. Coplien, there is described a mechanism known as Dynamic Multiple Inheritance for dynamically setting how an object is created. The idea presented is that the implementation of the new operator contains a switch statement, which according to the value of the variable will determine which implementation to use for an object. The variable is passed to new as a parameter. By employing this mechanism, the program instantiates the required type depending on the run-time value of the variable.
However, it is to be noted that once an object is created, its implementation is fixed for the lifetime of the object. Furthermore, the manner in which the switch variable is passed to new is not transparent to the programmer who must provide the implementation for passing the desired variable. Finally, the run-time type of the object differs based upon the implementation picked by the new operator.
In the Self language, an object can change its behavior many times during run-time but in each case it is considered a different object. Unlike languages based on the use of xe2x80x9cclassesxe2x80x9d and their xe2x80x9cinstancesxe2x80x9d, Self is based on the prototype concept. In Self, a program starts with an initial set of prototype objects, which are true objects in the classical sense. An application programmer needing another object with certain properties, chooses the prototype xe2x80x9cnearestxe2x80x9d to the required one, copies it and changes the data slots (fields) and method slots as required. Thus, an object is not an instance of a class (prototype), but rather is a copy of a prototype or a different object altogether. In a vanilla object-oriented language like C++ or Java, the behavior of the object is fixed and all objects of the same class implement the same methods in the same way and thus exhibit the same behavior. It would clearly be desirable to adapt such a language so as to allow the behavior of an object to be changed dynamically during run-time, whilst maintaining the fact that the object is an instance of the same class all the time. At the same time, different instances of the same class having different implementations at any particular instance in time must be allowed.
It is an object of the invention to provide a data structure and associated mechanism for implementing an object oriented programming language, which allows different implementations of a method to be executed dynamically during run-time, without requiring instantiation of an object of a different class.
According to a first aspect of the invention, there is provided a data structure and associated mechanism for implementing object oriented programming language, comprising:
at least two code blocks for at least one method of an object of a specified class, each of said code blocks containing a different implementation of said at least one method, and
an access mechanism for accessing a desired code block at run-time on a per object instance basis so as to allow selection of a desired implementation of said at least one method without requiring instantiation of an object of a different class;
said selection of which implementation to invoke being integrated into an existing invocation method of said language and thus being transparent to a calling application invoking said at least one method.
According to a second aspect of the invention, there is provided a method for implementing an object oriented programming language, comprising:
(a) providing at least two code blocks for at least one method of an object of a specified class, each of said code blocks containing a different implementation of said at least one method, and
(b) accessing a desired code block at run-time on a per object instance basis so as to allow selection of a desired implementation of said at least one method without requiring instantiation of an object of a different class;
said selection of which implementation to invoke being integrated into an existing invocation method of said language and thus being transparent to a calling application invoking said at least one method.
The invention describes a mechanism that allows an object to behave differently at different points in time during run-time so that different method implementations can be associated with the object according to circumstances dictated, not in advance by the programmer, but rather by the environment. Thus, consider three different instances of a vector class, all of which are accessed by multiple nodes in a distributed application:
vector A: this vector is relatively small, access is in bursts and at any given time localized to a thread, and the accesses involve a mixture of reads and writes;
vector B: this vector is relatively large, the accesses are sparse and not localized to a single thread at any given time, and the accesses involve a mixture of reads and writes;
vector C: this vector is relatively large, after a period of initialization all of the accesses are read-only, and the accesses are continuous and not localized to a single thread.
It seems fairly clear that different implementations would be required for each of the three cases to give optimal performance. For vector A, a caching proxy is needed which allows only exclusive caching; for vector B, a simple proxy which remotes all accesses should be used; whilst for vector C there is required a proxy that supports multiple readers, single writers. The invention provides a mechanism that allows different implementations to be defined on a per object instance basis.
Thus, the invention allows for only a single vector to be defined in the application but for that single vector to behave like vector A or vector B or vector C at different points in its life. This is made possible, according to the invention, by allowing the behavior of the proxies for the given vector object to be changed, after the vector object is created, based for example upon run-time profiling information.